package com.liuqi.voicenotes.reminder

import android.annotation.SuppressLint
import android.app.AlarmManager
import android.app.AlarmManager.AlarmClockInfo
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.os.Build
import com.liuqi.voicenotes.MainActivity

object ReminderScheduler {
    private const val PREFS = "voicenotes_prefs"
    private const val KEY_LEAD_MINUTES = "lead_time_minutes"

    fun getLeadMinutes(context: Context): Int {
        val sp = context.getSharedPreferences(PREFS, Context.MODE_PRIVATE)
        return sp.getInt(KEY_LEAD_MINUTES, 10)
    }

    fun setLeadMinutes(context: Context, minutes: Int) {
        val sp = context.getSharedPreferences(PREFS, Context.MODE_PRIVATE)
        sp.edit().putInt(KEY_LEAD_MINUTES, minutes.coerceIn(0, 120)).apply()
    }

    @SuppressLint("ScheduleExactAlarm")
    fun scheduleForTask(context: Context, taskId: Long, title: String, atMillis: Long) {
        val am = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager

        // 先取消旧的
        cancelForTask(context, taskId)

        // 主提醒
        val intentMain = Intent(context, ReminderReceiver::class.java).apply {
            putExtra("title", title)
            putExtra("taskId", taskId)
            putExtra("is_pre", false)
        }
        val piMain = PendingIntent.getBroadcast(
            context,
            (taskId * 10 + 1).toInt(),
            intentMain,
            PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
        )
        setExactCompat(context, am, atMillis, piMain)

        // 提前提醒
        val leadMillis = getLeadMinutes(context) * 60_000L
        val preMillis = atMillis - leadMillis
        if (leadMillis > 0 && preMillis > System.currentTimeMillis()) {
            val intentPre = Intent(context, ReminderReceiver::class.java).apply {
                putExtra("title", title)
                putExtra("taskId", taskId)
                putExtra("is_pre", true)
            }
            val piPre = PendingIntent.getBroadcast(
                context,
                (taskId * 10 + 2).toInt(),
                intentPre,
                PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
            )
            setExactCompat(context, am, preMillis, piPre)
        }
    }

    fun cancelForTask(context: Context, taskId: Long) {
        val am = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
        fun cancel(code: Int) {
            val intent = Intent(context, ReminderReceiver::class.java)
            val pi = PendingIntent.getBroadcast(
                context,
                (taskId * 10 + code).toInt(),
                intent,
                PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
            )
            am.cancel(pi)
        }
        cancel(1)
        cancel(2)
    }

    @SuppressLint("ScheduleExactAlarm")
    private fun setExactCompat(context: Context, am: AlarmManager, atMillis: Long, operation: PendingIntent) {
        val canExact = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) am.canScheduleExactAlarms() else true
        if (canExact) {
            am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, atMillis, operation)
        } else {
            // 无法使用精确闹钟时，退化为闹钟模式，系统会显示闹钟指示但能准时触发
            val showIntent = PendingIntent.getActivity(
                context,
                (System.currentTimeMillis() % Int.MAX_VALUE).toInt(),
                Intent(context, MainActivity::class.java).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP),
                PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
            )
            val info = AlarmClockInfo(atMillis, showIntent)
            am.setAlarmClock(info, operation)
        }
    }
}